home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Collection of Tools & Utilities
/
Collection of Tools and Utilities.iso
/
edit
/
elv18src.zip
/
tio.c
< prev
next >
Wrap
C/C++ Source or Header
|
1994-01-10
|
27KB
|
1,257 lines
/* tio.c */
/* Author:
* Steve Kirkendall
* 14407 SW Teal Blvd. #C
* Beaverton, OR 97005
* kirkenda@cs.pdx.edu
*/
/* This file contains terminal I/O functions */
#include "config.h"
#include <string.h>
#include "vi.h"
#include "ctype.h"
extern char *printable();
static int showmsg P_((void));
/* This function reads in a line from the terminal. It simulates the normal
* line editing for cooked input, with support for backspace, ^U, and ^V.
*
* Support for ^W and ^P added by sdw, Nov. 1993.
*
* It tries to hide the extra ^O that a "visual" map inserts before each
* character. When it reads a ^O, it discards it and reads the next character.
* Then only exception is after a ^V which itself was not preceded by a ^O, the
* character immediately following the ^V is accepted even if it is a ^O.
*
* Eventually I hope to make it use ^O to access a history of previously
* entered commands. ^Ok to move back, ^Ol to move forward, etc. This way,
* the standard arrow key mappings can be used to access history easily, and
* users who don't have the benefit of arrow keys will still be able to use
* history. But that hasn't happened yet.
*/
int vgets(prompt, buf, bsize)
int prompt; /* the prompt character, or '\0' for none */
char *buf; /* buffer into which the string is read */
int bsize; /* size of the buffer */
{
int len; /* how much we've read so far */
int ch; /* a character from the user */
int quoted; /* is the next char quoted? */
int tab; /* column position of cursor */
char widths[132]; /* widths of characters */
int word; /* index of first letter of word */
#ifndef NO_DIGRAPH
int erased; /* 0, or first char of a digraph */
#endif
#ifndef NO_EXTENSIONS
int ctrlO; /* boolean: was last character ^O ? */
#endif
#if 1 /* [sdw] */
int cbsize; /* size of cut buffer to be pasted */
#endif
/* show the prompt */
move(LINES - 1, 0);
tab = 0;
if (prompt)
{
addch(prompt);
tab = 1;
}
clrtoeol();
refresh();
/* read in the line */
#ifndef NO_DIGRAPH
erased =
#endif
#ifndef NO_EXTENSIONS
ctrlO =
#endif
quoted = len = 0;
for (;;)
{
#ifndef NO_ABBR
if (quoted || mode == MODE_EX)
{
ch = getkey(0);
}
else
{
/* maybe expand an abbreviation while getting key */
ch = getabkey(WHEN_EX, buf, len);
}
#else
ch = getkey(0);
#endif
#ifndef NO_EXTENSIONS
if (ctrlO || !quoted && ch == ctrl('O'))
{
ch = getkey(quoted ? 0 : WHEN_EX);
if (ch == ctrl('V'))
{
ctrlO = TRUE;
}
}
#endif
/* some special conversions */
#if 0
if (ch == ctrl('D') && len == 0)
ch = ctrl('[');
#endif
#ifndef NO_DIGRAPH
if (*o_digraph && erased != 0 && ch != '\b')
{
ch = digraph(erased, ch);
erased = 0;
}
#endif
/* inhibit detection of special chars (except ^J) after a ^V */
if (quoted && ch != '\n')
{
ch |= 256;
}
/* process the character */
switch(ch)
{
case ctrl('V'):
qaddch('^');
qaddch('\b');
quoted = TRUE;
break;
case ctrl('D'):
return -1;
case ctrl('['):
case '\n':
#if OSK
case '\l':
#else
case '\r':
#endif
clrtoeol();
goto BreakBreak;
#ifndef CRUNCH
case ctrl('U'):
while (len > 0)
{
len--;
while (widths[len]-- > 0)
{
qaddch('\b');
qaddch(' ');
qaddch('\b');
}
}
break;
/* [sdw] -- verbose but functional... */
/* erase over previous Word */
case ctrl('W'):
if (len == 0)
{
return -1;
}
while (len > 0
&& (buf[len-1] == ' ' || buf[len-1] == '\t'))
{
len--;
# ifndef NO_DIGRAPH
erased = buf[len];
# endif
for (ch = widths[len]; ch > 0; ch--)
addch('\b');
tab -= widths[len];
}
while (len > 0
&& buf[len-1] != ' ' && buf[len-1] != '\t')
{
len--;
# ifndef NO_DIGRAPH
erased = buf[len];
# endif
for (ch = widths[len]; ch > 0; ch--)
addch('\b');
tab -= widths[len];
}
if (mode == MODE_EX)
{
clrtoeol();
}
break;
#endif
case '\b':
if (len > 0)
{
len--;
#ifndef NO_DIGRAPH
erased = buf[len];
#endif
for (ch = widths[len]; ch > 0; ch--)
addch('\b');
if (mode == MODE_EX)
{
clrtoeol();
}
tab -= widths[len];
}
else
{
return -1;
}
break;
#if 1 /* [sdw] */
/* paste in contents of anonymous buffer */
case ctrl('P'):
cbsize = cb2str(0, tmpblk.c, BLKSIZE);
if (cbsize > 0 && cbsize != BLKSIZE)
{
execmap(0, tmpblk.c, FALSE);
}
break;
#endif
default:
/* strip off quotation bit */
if (ch & 256)
{
ch &= ~256;
qaddch(' ');
qaddch('\b');
}
/* add & echo the char */
if (len < bsize - 1)
{
if (ch == '\t' && !quoted)
{
widths[len] = *o_tabstop - (tab % *o_tabstop);
addstr(" " + 8 - widths[len]);
tab += widths[len];
}
else if (ch > 0 && ch < ' ') /* > 0 by GB */
{
addch('^');
addch(ch + '@');
widths[len] = 2;
tab += 2;
}
else if (ch == '\177')
{
addch('^');
addch('?');
widths[len] = 2;
tab += 2;
}
else
{
addch(ch);
widths[len] = 1;
tab++;
}
buf[len++] = ch;
}
else
{
beep();
}
#ifndef NO_EXTENSIONS
ctrlO =
#endif
quoted = FALSE;
}
}
BreakBreak:
refresh();
buf[len] = '\0';
return len;
}
static int manymsgs; /* This variable keeps msgs from overwriting each other */
static char pmsg[80]; /* previous message (waiting to be displayed) */
static int showmsg()
{
/* if there is no message to show, then don't */
if (!manymsgs)
return FALSE;
/* display the message */
move(LINES - 1, 0);
if (*pmsg)
{
standout();
qaddch(' ');
qaddstr(pmsg);
qaddch(' ');
standend();
}
clrtoeol();
manymsgs = FALSE;
return TRUE;
}
void endmsgs()
{
if (manymsgs)
{
showmsg();
addch('\n');
}
}
/* Write a message in an appropriate way. This should really be a varargs
* function, but there is no such thing as vwprintw. Hack!!!
*
* In MODE_EX or MODE_COLON, the message is written immediately, with a
* newline at the end.
*
* In MODE_VI, the message is stored in a character buffer. It is not
* displayed until getkey() is called. msg() will call getkey() itself,
* if necessary, to prevent messages from being lost.
*
* msg("") - clears the message line
* msg("%s %d", ...) - does a printf onto the message line
*/
#if NEWSTYLE
void msg (char *fmt, ...)
{
va_list ap;
va_start (ap, fmt);
#else
void msg(fmt, arg1, arg2, arg3, arg4, arg5, arg6, arg7)
char *fmt;
long arg1, arg2, arg3, arg4, arg5, arg6, arg7;
{
#endif
if (mode != MODE_VI)
{
#if NEWSTYLE
vsprintf (pmsg, fmt, ap);
#else
sprintf(pmsg, fmt, arg1, arg2, arg3, arg4, arg5, arg6, arg7);
#endif
qaddstr(pmsg);
addch('\n');
exrefresh();
}
else
{
/* wait for keypress between consecutive msgs */
if (manymsgs)
{
getkey(WHEN_MSG);
}
/* real message */
#if NEWSTYLE
vsprintf (pmsg, fmt, ap);
#else
sprintf(pmsg, fmt, arg1, arg2, arg3, arg4, arg5, arg6, arg7);
#endif
if (*fmt)
{
manymsgs = TRUE;
}
}
#ifdef __STDC__
va_end (ap);
#endif
}
/* This function calls refresh() if the option exrefresh is set */
void exrefresh()
{
char *scan;
/* If this ex command wrote ANYTHING set exwrote so vi's : command
* can tell that it must wait for a user keystroke before redrawing.
*/
for (scan=kbuf; scan<stdscr; scan++)
if (*scan == '\n')
exwrote = TRUE;
/* now we do the refresh thing */
if (*o_exrefresh)
{
refresh();
}
else
{
wqrefresh();
}
if (mode != MODE_VI)
{
manymsgs = FALSE;
}
}
/* This structure is used to store maps and abbreviations. The distinction
* between them is that maps are stored in the list referenced by the "maps"
* pointer, while abbreviations are referenced by the "abbrs" pointer.
*/
typedef struct _map
{
struct _map *next; /* another abbreviation */
short len; /* length of the "rawin" characters */
short flags; /* various flags */
char *label; /* label of the map/abbr, or NULL */
char *rawin; /* the "rawin" characters */
char *cooked;/* the "cooked" characters */
} MAP;
static char keybuf[KEYBUFSIZE];
static int cend; /* end of input characters